#include "gtest/gtest.h"
#include "mock/event_handler_mock.cc"
#include "event.h"
#include "spdlog/spdlog.h"

using namespace simple;

TEST(event_test, registerHandler) {
    std::shared_ptr<HandlerBaseMock> handlerMock1 = std::make_shared<HandlerBaseMock>();
    EXPECT_CALL(*handlerMock1, eventName()).WillRepeatedly(testing::Return("event1"));
    EXPECT_CALL(*handlerMock1, register_hook()).Times(1).WillRepeatedly(testing::Return());
    EXPECT_CALL(*handlerMock1, unRegister_hook()).Times(1).WillRepeatedly(testing::Return());

    auto handlerMock2 = std::make_shared<HandlerBaseMock>();
    EXPECT_CALL(*handlerMock2, eventName()).WillRepeatedly(testing::Return("event1"));
    EXPECT_CALL(*handlerMock2, register_hook()).Times(1).WillRepeatedly(testing::Return());
    EXPECT_CALL(*handlerMock2, unRegister_hook()).Times(1).WillRepeatedly(testing::Return());

    Event::registerHandler(handlerMock1);
    Event::registerHandler(handlerMock2);

    auto &handlers = Event::getHandlers();
    EXPECT_EQ(handlers.size(), 1);
    EXPECT_EQ(handlers.at(handlerMock1->eventName()).size(), 2);
    Event::resetHandlers();
}

TEST(event_test, unRegisterHandler) {
    std::shared_ptr<HandlerBaseMock> handlerMock1 = std::make_shared<HandlerBaseMock>();
    EXPECT_CALL(*handlerMock1, eventName()).WillRepeatedly(testing::Return("event1"));
    EXPECT_CALL(*handlerMock1, register_hook()).Times(1).WillRepeatedly(testing::Return());
    EXPECT_CALL(*handlerMock1, unRegister_hook()).Times(1).WillRepeatedly(testing::Return());

    Event::registerHandler(handlerMock1);
    Event::unRegisterHandler(handlerMock1);

    auto &handlers = Event::getHandlers();
    EXPECT_EQ(handlers.size(), 0);
}

TEST(event_test, publishEvent) {
    auto assertion = [](auto session) {
        spdlog::info("session fd: {}", session->socketFd());
        EXPECT_EQ(session->socketFd(), 2);
    };

    std::shared_ptr<HandlerBaseMock> handlerMock1 = std::make_shared<HandlerBaseMock>();
    EXPECT_CALL(*handlerMock1, eventName()).WillRepeatedly(testing::Return("session"));
    EXPECT_CALL(*handlerMock1, register_hook()).Times(1).WillRepeatedly(testing::Return());
    EXPECT_CALL(*handlerMock1, unRegister_hook()).Times(1).WillRepeatedly(testing::Return());
    EXPECT_CALL(*handlerMock1, onEvent(testing::_)).WillRepeatedly(testing::Invoke(assertion));

    Event::registerHandler(handlerMock1);

    Session session(2);
    Event::publishEvent("session", &session);
    Session *session_ptr = &session;
    Event::publishEvent("session", session_ptr);

    Event::resetHandlers();
}